﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Xml.Linq;
using SGP;
//Need vectors for cirlces

namespace Particle_Editor
{
    public partial class Form1 : Form
    {
        SGP.ManagedDirect3D d3D;// = SGP.ManagedDirect3D.Instance;
        SGP.ManagedTextureManager tm;// = SGP.ManagedTextureManager.Instance;
        bool looping = true;
        Random rand = new Random();
        public Form1(){
            InitializeComponent();
            ShapeComboBox.SelectedItem = "Point";
            lastSpawn = System.DateTime.Now;
            particleTracker = new List<Particle>();
            spawnDelay  = (float)SpawnDelayNumericUpDown.Value;
            scale       = (float)StartScaleNumericUpDown.Value;
            endScale    = (float)EndScaleNumericUpDown.Value;
            lifeMin     = (float)LifeMinNumericUpDown.Value;
            lifeMax     = (float)LifeMaxNumericUpDown.Value;
            velX        = (float)VelXNumericUpDown.Value;
            velY        = (float)VelYNumericUpDown.Value;
            endVelX     = (float)EndVelXNumericUpDown.Value;
            endVelY     = (float)EndVelYNumericUpDown.Value;
            circleRange = (float)RangeNumericUpDown.Value;
            squareLength= (float)SquareLengthNumericUpDown.Value;
            squareHeight= (float)SquareHeightNumericUpDown.Value;
            lineLength  = (float)LengthNumericUpDown.Value;
            startColor  = StartColorTextBox.BackColor;
            endColor    = EndColorTextBox.BackColor;
            BackgroundTextBox.BackColor = backgroundColor;
            startRot    = 0;
            endRot      = 0;
            mPartSize   = new Size(5, 5);
            //Calculate the center of the screen for the position
            posX = EmitterGraphicsPanel.Size.Width / 2;
            posY = EmitterGraphicsPanel.Size.Height / 2;
            image = -1;
        }
    //Emitter side
        float posX          = 0.0f;
        float posY          = 0.0f;
        float spawnDelay    = 0.0f;
        bool stopSpawning   = false;
        String shape        = "Point";
        float circleRange   = 0.0f;
        float lineLength    = 0.0f;
        float squareLength  = 0.0f;
        float squareHeight  = 0.0f;
        List<Particle> particleTracker;
        DateTime lastSpawn;
        TimeSpan spawnYet;

        public float SpawnDelay
        {
            get { return spawnDelay; }
            set { spawnDelay = value; }
        }
        public bool StopSpawning
        {
            get { return stopSpawning; }
            set { stopSpawning = value; }
        }
        public String Shape
        {
            get { return shape; }
            set { shape = value; }
        }
        public float CircleRange
        {
            get { return circleRange; }
            set { circleRange = value; }
        }
        public float LineLength
        {
            get { return lineLength; }
            set { lineLength = value; }
        }
        public float SquareLength
        {
            get { return squareLength; }
            set { squareLength = value; }
        }
        public float SquareHeight
        {
            get { return squareHeight; }
            set { squareHeight = value; }
        }
        public bool Looping{
            get{return looping;}
            set{looping = value;}
        }

    //Particle side
        int image;
        String imageLoc;
        float scale;
        float endScale;
        float lifeMin;
        float lifeMax;
        float startVelX;
        float startVelY;
        float velX;
        float velY;
        float endVelX;
        float endVelY;
        int startRot;
        int endRot;
        Color endColor;
        Color startColor;

        public class Particle{
            public Particle(int _image, float _posX, float _posY, float _scale, float _endScale,
                float _lifeMin, float _life, /*float _lifeMax,*/ float _vX, float _vY, float _endvX, float _endvY, 
                float _R, float _endR, Color _start, Color _end, Size _partSize){
                image = _image;
                startTime = System.DateTime.Now;
                lastUpdate = System.DateTime.Now;
                posX = _posX;
                posY = _posY;
                scale = _scale;
                currScale = _scale;
                endScale = _endScale;
                lifeMin = _lifeMin;
                life = _life;
                lifeOffset = life;
                startVelX = velX = _vX;
                startVelY = velY = _vY;
                endVelX = _endvX;
                endVelY = _endvY;
                startRot = rot = _R;
                endRot = _endR;
                startColor = currColor = _start;
                endColor = _end;
                partSize = _partSize;
            }
            int image;
            float posX;
            float posY;
            float scale;
            float currScale;
            float endScale;
            float lifeMin;
            float life;
            float lifeOffset;
            float startVelX;
            float startVelY;
            float velX;
            float velY;
            float endVelX;
            float endVelY;
            float startRot;
            float rot;
            float endRot;
            Size partSize;
            Color endColor;
            Color currColor;
            Color startColor;
            DateTime startTime;
            DateTime lastUpdate;

            public int Image{
                get { return image; }
                set { image = value; }
            }
            public float PosX{
                get { return posX; }
                set { posX = value; }
            }
            public float PosY{
                get { return posY; }
                set { posY = value; }
            }
            public float LifeMin{
                get { return lifeMin; }
                set { lifeMin = value; }
            }
            public float Life{
                get { return life; }
                set { life = value; }
            }
            public float LifeOffset{
                get { return lifeOffset; }
                set { lifeOffset = value; }
            }
            public float VelX{
                get { return velX; }
                set { velX = value; }
            }
            public float VelY{
                get { return velY; }
                set { velY = value; }
            }
            public float StartVelX{
                get { return startVelX; }
                set { startVelX = value; }
            }
            public float StartVelY{
                get { return startVelY; }
                set { startVelY = value; }
            }
            public float EndVelX{
                get { return endVelX; }
                set { endVelX = value; }
            }
            public float EndVelY{
                get { return endVelY; }
                set { endVelY = value; }
            }
            public float StartRot{
                get { return startRot; }
                set { startRot = value; }
            }
            public float Rot{
                get { return rot; }
                set { rot = value; }
            }
            public float EndRot{
                get { return endRot; }
                set { endRot = value; }
            }
            public Size PartSize{
                get { return partSize; }
                set { partSize = value; }
            }
            public Color StartColor{
                get{return startColor;}
            }
            public Color Color{
                get{return currColor;}
                set{currColor = value;}
            }
            public Color EndColor{
                get{return endColor;}
            }
            public DateTime StartTime{
                get { return startTime; }
                set { startTime = value; }
            }
            public DateTime LastUpdate{
                get { return lastUpdate; }
                set { lastUpdate = value; }
            }
            public float Scale{
                get { return currScale; }
                set { currScale = value; }
            }
            public float StartScale{
                get { return scale; }
                set { scale = value; }
            }
            public float EndScale
            {
                get { return endScale; }
                set { endScale = value; }
            }
        }

        public int Image{
            get { return image; }
            set { image = value; }
        }
        public new float Scale{
            get { return scale; }
            set { scale = value; }
        }
        public float EndScale{
            get { return endScale; }
            set { endScale = value; }
        }
        public float LifeMin{
            get { return lifeMin; }
            set { lifeMin = value; }
        }
        public float LifeMax{
            get { return lifeMax; }
            set { lifeMax = value; }
        }
        public float StartVelX{
            get { return startVelX; }
            set { startVelX = value; }
        }
        public float StartVelY{
            get { return startVelY; }
            set { startVelY = value; }
        }
        public float EndVelX{
            get { return endVelX; }
            set { endVelX = value; }
        }
        public float EndVelY{
            get { return endVelY; }
            set { endVelY = value; }
        }
        public int StartRot{
            get { return startRot; }
            set { startRot = value; }
        }
        public int EndRot{
            get { return endRot; }
            set { endRot = value; }
        }
        public Color EndColor{
          get{return endColor;}
          set{endColor = value;}
        }
        public Color StartColor{
            get { return startColor; }
            set { startColor = value; }
        }
        
    //Particle Image Editor side
        Color backgroundColor = Color.Beige;
        Color currColor;
        Size mPartSize;

        public Color CurrColor{
            get { return currColor; }
            set { currColor = value; }
        }
        public Color BackgroundColor{
            get { return backgroundColor; }
            set { backgroundColor = value; }
        }
        public Size MPartSize{
            get{return mPartSize;}
            set{mPartSize = value;}
        }

    //Functions
        private void StopSpawnBox_CheckedChanged(object sender, EventArgs e){
            stopSpawning = StopSpawnBox.Checked;
        }
        private void SpawnDelayNumericUpDown_ValueChanged(object sender, EventArgs e){
            spawnDelay = (float)SpawnDelayNumericUpDown.Value;
        }
        private void ShapeComboBox_SelectedIndexChanged(object sender, EventArgs e){
            if(InvertCheckBox.Checked /*&& ShapeComboBox.SelectedIndex.ToString() == "Point"*/){
                ShapeComboBox.SelectedIndex = 2;
            }
            shape = ShapeComboBox.SelectedItem.ToString();
            switch(shape){
                case "Point":{
                    CircleGroupBox.Visible = false;
                    SquareGroupBox.Visible = false;
                    LineGroupBox.Visible = false;
                    break;
                }
                case "Circle":{
                    CircleGroupBox.Visible = true;
                    SquareGroupBox.Visible = false;
                    LineGroupBox.Visible = false;
                    break;
                }
                case "Square":{
                    CircleGroupBox.Visible = false;
                    SquareGroupBox.Visible = true;
                    LineGroupBox.Visible = false;
                    break;
                }
                case "Line (Horizon)":{
                    CircleGroupBox.Visible = false;
                    SquareGroupBox.Visible = false;
                    LineGroupBox.Visible = true;
                    break;
                }
                case "Line (Vert)":{
                    CircleGroupBox.Visible = false;
                    SquareGroupBox.Visible = false;
                    LineGroupBox.Visible = true;
                    break;
                }
            }
        }
        private void RangeNumericUpDown_ValueChanged(object sender, EventArgs e){
            circleRange = (float)RangeNumericUpDown.Value;
        }
        private void LengthNumericUpDown_ValueChanged(object sender, EventArgs e){
            lineLength = (float)LengthNumericUpDown.Value;
        }
        private void SquareLengthNumericUpDown_ValueChanged(object sender, EventArgs e){
            squareLength = (float)SquareLengthNumericUpDown.Value;
        }
        private void SquareHeightNumericUpDown_ValueChanged(object sender, EventArgs e){
            squareHeight = (float)SquareHeightNumericUpDown.Value;
        }
        private void SquareGroupBox_Enter(object sender, EventArgs e){
            squareHeight = (float)SquareHeightNumericUpDown.Value;
        }
        private void ScaleNumericUpDown_ValueChanged(object sender, EventArgs e){
            scale = (float)StartScaleNumericUpDown.Value;
        }
        private void EndingScaleNumericUpDown_ValueChanged(object sender, EventArgs e){
            endScale = (float)EndScaleNumericUpDown.Value;
        }
        private void LifeMinNumericUpDown_ValueChanged(object sender, EventArgs e){
            if(LifeMinNumericUpDown.Value <= LifeMaxNumericUpDown.Value){
                lifeMin = (float)LifeMinNumericUpDown.Value;
            }
            else{
                LifeMinNumericUpDown.Value = (decimal)lifeMin;
            }
        }
        private void LifeMaxNumericUpDown_ValueChanged(object sender, EventArgs e){
            if(LifeMaxNumericUpDown.Value >= LifeMinNumericUpDown.Value){
                lifeMax = (float)LifeMaxNumericUpDown.Value;
            }
            else{
                LifeMaxNumericUpDown.Value = (decimal)lifeMax;
            }
        }
        private void VelXNumericUpDown_ValueChanged(object sender, EventArgs e){
            velX = (float)VelXNumericUpDown.Value;
        }
        private void VelYNumericUpDown_ValueChanged(object sender, EventArgs e){
            velY = (float)VelYNumericUpDown.Value;
        }
        private void EndVelXNumericUpDown_ValueChanged(object sender, EventArgs e){
            EndVelX = (float)EndVelXNumericUpDown.Value;
        }
        private void EndVelYNumericUpDown_ValueChanged(object sender, EventArgs e){
            EndVelY = (float)EndVelYNumericUpDown.Value;
        }

        public new void Update(){
            //Update existing particles
            List<Particle> dead = new List<Particle>();
            foreach(Particle p in particleTracker){
            //Check lifespan
                TimeSpan check = System.DateTime.Now - p.StartTime;
                if(check.TotalSeconds > p.Life){
                    //Despawn
                    dead.Add(p);
                    continue;
                }
                TimeSpan offset = System.DateTime.Now - p.LastUpdate;
                p.LifeOffset -= (float)offset.TotalSeconds;
            //Update position
                p.PosX = p.PosX + (p.VelX * (float)offset.TotalSeconds);
                p.PosY = p.PosY + (p.VelY * (float)offset.TotalSeconds);
            //Update velocity
                p.VelX = p.VelX + (p.EndVelX - p.StartVelX) * ((float)offset.TotalSeconds / p.Life);
                p.VelY = p.VelY + (p.EndVelY - p.StartVelY) * ((float)offset.TotalSeconds / p.Life);
            //Update Color
                //m_nColorA += (int)(((ParentEmitter.NEndAlpha - ParentEmitter.NStartAlpha)) * fElapsedTime);
                float aB = p.Color.A + (int)(((p.EndColor.A - p.StartColor.A) / (p.LifeOffset /*- p.LifeMin*/)) * offset.TotalSeconds);
                float rB = p.Color.R + (int)(((p.EndColor.R - p.StartColor.R) / (p.LifeOffset /*- p.LifeMin*/)) * offset.TotalSeconds);
                float gB = p.Color.G + (int)(((p.EndColor.G - p.StartColor.G) / (p.LifeOffset /*- p.LifeMin*/)) * offset.TotalSeconds);
                float bB = p.Color.B + (int)(((p.EndColor.B - p.StartColor.B) / (p.LifeOffset /*- p.LifeMin*/)) * offset.TotalSeconds);
                float a = p.Color.A + ((p.EndColor.A - p.StartColor.A)/* / p.Life*/ * ((float)offset.TotalSeconds));
                float r = p.Color.R + ((p.EndColor.R - p.StartColor.R)/* / p.Life*/ * ((float)offset.TotalSeconds));
                float g = p.Color.G + ((p.EndColor.G - p.StartColor.G)/* / p.Life*/ * ((float)offset.TotalSeconds));
                float b = p.Color.B + ((p.EndColor.B - p.StartColor.B)/* / p.Life*/ * ((float)offset.TotalSeconds));
                //Don't go under
                if(a < 0.0f){a = 0.0f;}
                if(r < 0.0f){r = 0.0f;}
                if(g < 0.0f){g = 0.0f;}
                if(b < 0.0f){b = 0.0f;}
                if(aB < 0.0f){aB = 0.0f;}
                if(rB < 0.0f){rB = 0.0f;}
                if(gB < 0.0f){gB = 0.0f;}
                if(bB < 0.0f){bB = 0.0f;}
                //Don't go over
                if(a > 255.0f){a = 255.0f;}
                if(r > 255.0f){r = 255.0f;}
                if(g > 255.0f){g = 255.0f;}
                if(b > 255.0f){b = 255.0f;}
                if(aB > 255.0f){aB = 255.0f;}
                if(rB > 255.0f){rB = 255.0f;}
                if(gB > 255.0f){gB = 255.0f;}
                if(bB > 255.0f){bB = 255.0f;}
                //Round up
                //if(a % 1 >= 0.5f){a = (a > (float)p.Color.A) ? a + 1 : a - 1;}
                //if(r % 1 >= 0.5f){r = (r > (float)p.Color.R) ? r + 1 : r - 1;}
                //if(g % 1 >= 0.5f){g = (g > (float)p.Color.G) ? g + 1 : g - 1;}
                //if(b % 1 >= 0.5f){b = (b > (float)p.Color.B) ? b + 1 : b - 1;}
                /*if(a == 255 && r == 0 && g == 0 && b == 0){

                }
                else if(b >= 50){
                    a = 255;
                }*/
                p.Color = Color.FromArgb((int)a, (int)r, (int)g, (int)b);
              //  p.Color = Color.FromArgb((int)aB, (int)rB, (int)gB, (int)bB);
            //Update Scale
                p.Scale = p.Scale + (p.EndScale - p.StartScale) * ((float)offset.TotalSeconds / p.Life);
            //Update Rotation
                p.Rot = p.Rot + (p.EndRot - p.StartRot) * ((float)offset.TotalSeconds / p.Life);
            //Verify time for last update
                p.LastUpdate = System.DateTime.Now;
            }
            //Remove any dead particles
            foreach(Particle p in dead){
                particleTracker.Remove(p);
            }
            dead.Clear();
            //Determine if a new particle should be spawned
            spawnYet = System.DateTime.Now - lastSpawn;
            if(spawnYet.TotalSeconds > spawnDelay && !StopSpawnBox.Checked){
                //Determine if another spawn is allowed
                if(TestCheckBox.Checked && particleTracker.Count > PartCountNumericUpDown.Value){return;}
                //Spawn a new particle
                int tempMin = (int)(lifeMin * 1000);
                int tempMax = (int)(lifeMax * 1000);
                float life = rand.Next(tempMin, tempMax);
                life /= 1000;
                float _x = posX, _y = posY;
                //Particle position
                switch(shape){
                    case "Point":{
                        //Spawn it at that point
                        break;
                    }
                    case "Square":{
                        _x = rand.Next((int)(posX - (squareLength / 2)), (int)(posX + (squareLength / 2)));
                        _y = rand.Next((int)(posY - (squareHeight / 2)), (int)(posY + (squareHeight / 2)));
                        break;
                    }
                    case "Circle":{
//------------------------------------------------------
//------------------------------------------------------
                        break;
                    }
                    case "Line (Horizon)":{
                        _x = rand.Next((int)(posX - (lineLength / 2)), (int)(posX + (lineLength / 2)));
                        break;
                    }
                    case "Line (Vert)":{
                        _y = rand.Next((int)(posY - (lineLength / 2)), (int)(posY + (lineLength / 2)));
                        break;
                    }
                }
                float _velX = velX, _velY = velY;
                float _eVelX = endVelX, _eVelY = endVelY;
                if(!InvertCheckBox.Checked){
                    //Particle Velocity
                    if(RandVelCheckBox.Checked){
                        _velX = rand.Next((int)VelXNumericUpDown.Minimum, (int)VelXNumericUpDown.Maximum);
                        _velY = rand.Next((int)VelYNumericUpDown.Minimum, (int)VelYNumericUpDown.Maximum);
                    }
                    if(EndVelRandCheckBox.Checked){
                        _eVelX = rand.Next((int)EndVelXNumericUpDown.Minimum, (int)EndVelXNumericUpDown.Maximum);
                        _eVelY = rand.Next((int)EndVelYNumericUpDown.Minimum, (int)EndVelYNumericUpDown.Maximum);
                    }
                }
                else{
                    //Particle Velocity
                    _velX = (posX - _x) / (lifeMax - lifeMin);
                    _velY = (posY - _y) / (lifeMax - lifeMin);
                    _eVelX = _eVelY = 0.0f;
                }
                //Particle Rotation
                int _StartRot = startRot, _EndRot = endRot;
                if(RandRotCheckBox.Checked){
                    _StartRot = rand.Next((int)StartRotNumericUpDown.Minimum, (int)StartRotNumericUpDown.Maximum);
                    _EndRot = rand.Next((int)EndRotNumericUpDown.Minimum, (int)EndRotNumericUpDown.Maximum);
                }
                //Particle Color
                Color _Start, _End;
                int a, r, g, b;
                a = (int)StartAlphaNumericUpDown.Value;
                r = startColor.R;
                g = startColor.G;
                b = startColor.B;
                _Start = Color.FromArgb(a, r, g, b);
                a = (int)EndAlphaNumericUpDown.Value;
                r = EndColor.R;
                g = EndColor.G;
                b = EndColor.B;
                _End = Color.FromArgb(a, r, g, b);
                Particle newPart = new Particle(image, _x, _y, scale, endScale, lifeMin, life,
                    _velX, _velY, _eVelX, _eVelY, _StartRot, _EndRot, _Start, _End, mPartSize);
                particleTracker.Add(newPart);
                //reset the last spawn
                lastSpawn = System.DateTime.Now;
            }
        }
        public void Render(){
            if (ViewerTab.SelectedIndex == 0){
                d3D.Clear(EmitterGraphicsPanel, backgroundColor);
            }
            else if(ViewerTab.SelectedIndex == 1){
                d3D.Clear(ParticleGraphicsPanel, backgroundColor);
            }
            d3D.DeviceBegin();
            d3D.SpriteBegin();

            if(ViewerTab.SelectedIndex == 0){//Emitter Graphics Panel
            //    d3D.DrawLine(0, 5, 20, 25, Color.Red);
                //Display particles at current location
                foreach(Particle p in particleTracker){
                    //Render to the screen
                    //if(/*p.Color.R <= 150 && */p.Color.B <= 50){}
                    //else{
                    Rectangle rect2 = new Rectangle(0, 0, p.PartSize.Width, p.PartSize.Height);
                    tm.Draw(p.Image, (int)p.PosX - (int)((p.PartSize.Width * p.Scale) / 2), (int)p.PosY - (int)((p.PartSize.Height * p.Scale) / 2), 
                        p.Scale, p.Scale, rect2, (int)((p.PartSize.Width * p.Scale) / 2), (int)((p.PartSize.Height * p.Scale) / 2), p.Rot, p.Color);
                    //}
                }
            }
            else if(ViewerTab.SelectedIndex == 1){//Particle Graphics Panel
            //    d3D.DrawLine(0, 5, 20, 50, Color.Blue);
            }

            d3D.SpriteEnd();
            d3D.DeviceEnd();
            d3D.Present(EmitterGraphicsPanel);
        }
        public void Shutdown(){
            tm.ShutdownManagedTextureManager();
            tm = null;
            d3D.Shutdown();
            d3D = null;
        }

        private void EndColorTextBox_Click(object sender, EventArgs e){
            ColorDialog dlg = new ColorDialog();
                dlg.Color = EndColorTextBox.BackColor;
            if(DialogResult.OK == dlg.ShowDialog()){
                EndColorTextBox.BackColor = dlg.Color;
            }
            endColor = EndColorTextBox.BackColor;
        }
        private void StartColorTextBox_Click(object sender, EventArgs e){
            ColorDialog dlg = new ColorDialog();
            dlg.Color = StartColorTextBox.BackColor;
            if(DialogResult.OK == dlg.ShowDialog()){
                StartColorTextBox.BackColor = dlg.Color;
            }
            startColor = StartColorTextBox.BackColor;
        }
        private void CurrColorTextBox_Click(object sender, EventArgs e){
            ColorDialog dlg = new ColorDialog();
            dlg.Color = CurrColorTextBox.BackColor;
            if(DialogResult.OK == dlg.ShowDialog()){
                CurrColorTextBox.BackColor = dlg.Color;
            }
            currColor = CurrColorTextBox.BackColor;
        }
        private void BackgroundTextBox_Click(object sender, EventArgs e){
            ColorDialog dlg = new ColorDialog();
            dlg.Color = BackgroundTextBox.BackColor;
            if(DialogResult.OK == dlg.ShowDialog()){
                BackgroundTextBox.BackColor = dlg.Color;
            }
            backgroundColor = BackgroundTextBox.BackColor;
            EmitterGraphicsPanel.BackColor = backgroundColor;
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e){
            looping = false;
            this.Close();
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e){
            looping = false;
        }
        private void Form1_Load(object sender, EventArgs e){
            d3D = SGP.ManagedDirect3D.Instance;
            tm = SGP.ManagedTextureManager.Instance;
            d3D.InitManagedDirect3D(EmitterGraphicsPanel);
            d3D.InitManagedDirect3D(ParticleGraphicsPanel);
            tm.InitManagedTextureManager(d3D.Device, d3D.Sprite);
            //Load in a default particle
            imageLoc = "../../../resource\\Images\\blurred sharp star.png";
            image = tm.LoadTexture(imageLoc, 0);
            imageLoc = imageLoc.Remove(0, 6);
            PartWidthNumericUpDown.Value = 128M;
            PartHeightNumericUpDown.Value = 128M;
            /*ShapeComboBox.SelectedIndex = 3;
            LengthNumericUpDown.Value = 700M;
            StartScaleNumericUpDown.Value = .5M;
            EndScaleNumericUpDown.Value = .5M;
            VelXNumericUpDown.Value = 0.0M;
            VelYNumericUpDown.Value = 50.0M;
            EndVelXNumericUpDown.Value = 0.0M;
            EndVelYNumericUpDown.Value = 50.0M;
            posY = EmitterGraphicsPanel.Size.Height / 4;*/
        }
        private void RandVelCheckBox_CheckedChanged(object sender, EventArgs e){
            if(RandVelCheckBox.Checked){
                VelXNumericUpDown.Increment = 0.0M;
                VelYNumericUpDown.Increment = 0.0M;
            }
            else{
                VelXNumericUpDown.Increment = 0.25M;
                VelYNumericUpDown.Increment = 0.25M;
            }
        }
        private void EndVelRandCheckBox_CheckedChanged(object sender, EventArgs e){
            if(EndVelRandCheckBox.Checked){
                EndVelXNumericUpDown.Increment = 0.0M;
                EndVelYNumericUpDown.Increment = 0.0M;
            }
            else{
                EndVelXNumericUpDown.Increment = 0.25M;
                EndVelYNumericUpDown.Increment = 0.25M;
            }
        }
        private void RandRotCheckBox_CheckedChanged(object sender, EventArgs e){
            if(RandRotCheckBox.Checked){
                StartRotNumericUpDown.Increment = 0M;
                EndRotNumericUpDown.Increment = 0M;
            }
            else{
                StartRotNumericUpDown.Increment = 1M;
                EndRotNumericUpDown.Increment = 1M;
            }
        }        
        private void loadImageToolStripMenuItem_Click(object sender, EventArgs e){
            //Open dialog box to find file to load in
            OpenFileDialog dlg = new OpenFileDialog();
            if(DialogResult.OK == dlg.ShowDialog()){
                //Load it in
                imageLoc = dlg.SafeFileName;
                image = tm.LoadTexture(dlg.FileName, 0);
                imageLoc = "resource\\Images\\" + imageLoc;
            }
        }
        private void newToolStripMenuItem_Click(object sender, EventArgs e){
        //Reset everything to default values
            //Emitter Editor Tab
            SpawnDelayNumericUpDown.Value = 0.0M;
            StopSpawnBox.Checked = false;
            ShapeComboBox.SelectedItem = "Point";
            RangeNumericUpDown.Value = 100.0M;
            SquareLengthNumericUpDown.Value = 100.0M;
            SquareHeightNumericUpDown.Value = 100.0M;
            LengthNumericUpDown.Value = 100.0M;
            //Particle Editor Tab
            StartScaleNumericUpDown.Value = 1.0M;
            EndScaleNumericUpDown.Value = 1.0M;
            LifeMinNumericUpDown.Value = 1.0M;
            LifeMaxNumericUpDown.Value = 10.0M;
            StartColorTextBox.BackColor = Color.Red;
            EndColorTextBox.BackColor = Color.Blue;
            VelXNumericUpDown.Value = 1.0M;
            VelYNumericUpDown.Value = 1.0M;
            RandVelCheckBox.Checked = false;
            EndVelXNumericUpDown.Value = 1.0M;
            EndVelYNumericUpDown.Value = 1.0M;
            EndVelRandCheckBox.Checked = false;
            //Tool Window
            startRot    = 0;
            endRot      = 0;
            mPartSize = new Size(128, 128);
            //Emitter Viewer Tab
            lastSpawn = System.DateTime.Now;
            particleTracker.Clear();
            image = -1;
            image = tm.LoadTexture("../../blurred sharp star.png", 0);
                //Calculate the center of the screen for the position
            posX = EmitterGraphicsPanel.Size.Width / 2;
            posY = EmitterGraphicsPanel.Size.Height / 2;
        }
        private void EmitterGraphicsPanel_MouseClick(object sender, MouseEventArgs e){
            if(e.Button != MouseButtons.Left){return;}
            Point location = e.Location;
            posX = location.X;
            posY = location.Y;
        }
        private void EmitterGraphicsPanel_MouseMove(object sender, MouseEventArgs e){
            if(e.Button == MouseButtons.Left){
                Point location = e.Location;
                posX = location.X;
                posY = location.Y;
            }
        }
        private void loadToolStripMenuItem_Click(object sender, EventArgs e){
            //Read in and load an already existing editor system of information
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            if(DialogResult.OK == dlg.ShowDialog()){
                XElement xRoot = XElement.Load(dlg.FileName);
                //Emitter Attributes
                XElement xEmit = xRoot.Element("Emitter");
                XAttribute xShape = xEmit.Attribute("Shape");
                shape = xShape.Value;
                XAttribute xPosX = xEmit.Attribute("PosX");
                posX = Convert.ToInt32(xPosX.Value);
                XAttribute xPosY = xEmit.Attribute("PosY");
                posY = Convert.ToInt32(xPosY.Value);
                XAttribute xRange = xEmit.Attribute("Range");
                RangeNumericUpDown.Value = Convert.ToDecimal(xRange.Value);
                XAttribute xWidth = xEmit.Attribute("Width");
                SquareLengthNumericUpDown.Value = Convert.ToDecimal(xWidth.Value);
                XAttribute xHeight = xEmit.Attribute("Height");
                SquareHeightNumericUpDown.Value = Convert.ToDecimal(xHeight.Value);
                XAttribute xLength = xEmit.Attribute("Length");
                LengthNumericUpDown.Value = Convert.ToDecimal(xLength.Value);
                XAttribute xPartCount = xEmit.Attribute("MaxPartCount");
                PartCountNumericUpDown.Value = Convert.ToInt32(xPartCount.Value);
                XAttribute xDelay = xEmit.Attribute("Delay");
                SpawnDelayNumericUpDown.Value = Convert.ToDecimal(xDelay.Value);
                XAttribute xLoop = xEmit.Attribute("Loop");
                LoopCheckBox.Checked = Convert.ToBoolean(xLoop.Value);
                XAttribute xInvert = xEmit.Attribute("Invert");
                InvertCheckBox.Checked = Convert.ToBoolean(xInvert.Value);
                //Particle Attributes
                XElement xPart = xRoot.Element("Particle");
                XAttribute xImage = xPart.Attribute("Image");
                imageLoc = xPart.Value;
                XAttribute xPartWidth = xPart.Attribute("PartWidth");
                mPartSize.Width = Convert.ToInt32(xPartWidth.Value);
                XAttribute xPartHeight = xPart.Attribute("PartHeight");
                mPartSize.Height = Convert.ToInt32(xPartHeight.Value);
                XAttribute xStScale = xPart.Attribute("StartScale");
                StartScaleNumericUpDown.Value = Convert.ToDecimal(xStScale.Value);
                XAttribute xEndScale = xPart.Attribute("EndScale");
                EndScaleNumericUpDown.Value = Convert.ToDecimal(xEndScale.Value);
                XAttribute xLifeMin = xPart.Attribute("LifeMin");
                LifeMinNumericUpDown.Value = Convert.ToDecimal(xLifeMin.Value);
                XAttribute xLifeMax = xPart.Attribute("LifeMax");
                LifeMaxNumericUpDown.Value = Convert.ToDecimal(xLifeMax.Value);
                XAttribute xStVelX = xPart.Attribute("StartVelX");
                VelXNumericUpDown.Value = Convert.ToDecimal(xStVelX.Value);
                XAttribute xStVelY = xPart.Attribute("StartVelY");
                VelYNumericUpDown.Value = Convert.ToDecimal(xStVelY.Value);
                XAttribute xEndVelX = xPart.Attribute("EndVelX");
                EndVelXNumericUpDown.Value = Convert.ToDecimal(xEndVelX.Value);
                XAttribute xEndVelY = xPart.Attribute("EndVelY");
                EndVelYNumericUpDown.Value = Convert.ToDecimal(xEndVelY.Value);
                XAttribute xStRot = xPart.Attribute("StartRotate");
                startRot = (int)Convert.ToDecimal(xStRot.Value);
                XAttribute xEndRot = xPart.Attribute("EndRotate");
                endRot = (int)Convert.ToDecimal(xEndRot.Value);
                //Color Attributes
                XElement xColor = xRoot.Element("Color");
                int a, r, g, b;
                XAttribute xStA = xColor.Attribute("StartA");
                a = Convert.ToInt32(xStA.Value);
                XAttribute xStR = xColor.Attribute("StartR");
                r = Convert.ToInt32(xStR.Value);
                XAttribute xStG = xColor.Attribute("StartG");
                g = Convert.ToInt32(xStG.Value);
                XAttribute xStB = xColor.Attribute("StartB");
                b = Convert.ToInt32(xStB.Value);
                startColor = Color.FromArgb(a, r, g, b);
                StartAlphaNumericUpDown.Value = a;
                XAttribute xEndA = xColor.Attribute("EndA");
                a = Convert.ToInt32(xEndA.Value);
                XAttribute xEndR = xColor.Attribute("EndR");
                r = Convert.ToInt32(xEndR.Value);
                XAttribute xEndG = xColor.Attribute("EndG");
                g = Convert.ToInt32(xEndG.Value);
                XAttribute xEndB = xColor.Attribute("EndB");
                b = Convert.ToInt32(xEndB.Value);
                endColor = Color.FromArgb(a, r, g, b);
                EndAlphaNumericUpDown.Value = a;
            }
        }
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e){
            //Save out the current editor system information
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";
            if(DialogResult.OK == dlg.ShowDialog()){
                XElement xRoot = new XElement("Editor");
                //Emitter Attributes
                XElement xEmit = new XElement("Emitter");
                xRoot.Add(xEmit);
                XAttribute xShape = new XAttribute("Shape", shape.ToString());
                xEmit.Add(xShape);
                XAttribute xPosX = new XAttribute("PosX", posX);
                xEmit.Add(xPosX);
                XAttribute xPosY = new XAttribute("PosY", posY);
                xEmit.Add(xPosY);
                XAttribute xRange = new XAttribute("Range", circleRange);
                xEmit.Add(xRange);
                XAttribute xSqWidth = new XAttribute("Width", squareLength);
                xEmit.Add(xSqWidth);
                XAttribute xSqHeight = new XAttribute("Height", SquareHeight);
                xEmit.Add(xSqHeight);
                XAttribute xLength = new XAttribute("Length", lineLength);
                xEmit.Add(xLength);
                XAttribute xPartCount = new XAttribute("MaxPartCount", PartCountNumericUpDown.Value);
                xEmit.Add(xPartCount);
                XAttribute xDelay = new XAttribute("Delay", spawnDelay);
                xEmit.Add(xDelay);
                XAttribute xLoop = new XAttribute("Loop", LoopCheckBox.Checked);
                xEmit.Add(xLoop);
                XAttribute xInvert = new XAttribute("Invert", InvertCheckBox.Checked);
                xEmit.Add(xInvert);
                //Particle Attributes
                XElement xPart = new XElement("Particle");
                xRoot.Add(xPart);
                XAttribute xImage = new XAttribute("Image", imageLoc);
                xPart.Add(xImage);
                XAttribute xPartWidth = new XAttribute("PartWidth", mPartSize.Width);
                xPart.Add(xPartWidth);
                XAttribute xPartHeight = new XAttribute("PartHeight", mPartSize.Height);
                xPart.Add(xPartHeight);
                XAttribute xStScale = new XAttribute("StartScale", scale);
                xPart.Add(xStScale);
                XAttribute xEndScale = new XAttribute("EndScale", endScale);
                xPart.Add(xEndScale);
                XAttribute xLifeMin = new XAttribute("LifeMin", lifeMin);
                xPart.Add(xLifeMin);
                XAttribute xLifeMax = new XAttribute("LifeMax", lifeMax);
                xPart.Add(xLifeMax);
                XAttribute xStVelX = new XAttribute("StartVelX", (InvertCheckBox.Checked ? 0.0f : velX));
                xPart.Add(xStVelX);
                XAttribute xStVelY = new XAttribute("StartVelY", (InvertCheckBox.Checked ? 0.0f : velY));
                xPart.Add(xStVelY);
                XAttribute xEndVelX = new XAttribute("EndVelX", (InvertCheckBox.Checked ? 0.0f : endVelX));
                xPart.Add(xEndVelX);
                XAttribute xEndVelY = new XAttribute("EndVelY", (InvertCheckBox.Checked ? 0.0f : endVelY));
                xPart.Add(xEndVelY);
                XAttribute xStRot = new XAttribute("StartRotate", startRot);
                xPart.Add(xStRot);
                XAttribute xEndRot = new XAttribute("EndRotate", endRot);
                xPart.Add(xEndRot);
                //Color Attributes
                XElement xColor = new XElement("Color");
                xRoot.Add(xColor);
                XAttribute xStA = new XAttribute("StartA", (int)StartAlphaNumericUpDown.Value);
                xColor.Add(xStA);
                XAttribute xStR = new XAttribute("StartR", startColor.R);
                xColor.Add(xStR);
                XAttribute xStG = new XAttribute("StartG", startColor.G);
                xColor.Add(xStG);
                XAttribute xStB = new XAttribute("StartB", startColor.B);
                xColor.Add(xStB);
                XAttribute xEndA = new XAttribute("EndA", (int)EndAlphaNumericUpDown.Value);
                xColor.Add(xEndA);
                XAttribute xEndR = new XAttribute("EndR", endColor.R);
                xColor.Add(xEndR);
                XAttribute xEndG = new XAttribute("EndG", endColor.G);
                xColor.Add(xEndG);
                XAttribute xEndB = new XAttribute("EndB", endColor.B);
                xColor.Add(xEndB);

                xRoot.Save(dlg.FileName);
            }
        }
        private void PartWidthNumericUpDown_ValueChanged(object sender, EventArgs e){
            mPartSize.Width = (int)PartWidthNumericUpDown.Value;
        }
        private void PartHeightNumericUpDown_ValueChanged(object sender, EventArgs e){
            mPartSize.Height = (int)PartHeightNumericUpDown.Value;
        }
        private void EditAlphaNumericUpDown_ValueChanged(object sender, EventArgs e){
            int a = (int)EditAlphaNumericUpDown.Value;
            currColor = Color.FromArgb(a, currColor.R, currColor.G, currColor.B);
        }
        private void StartRotNumericUpDown_ValueChanged(object sender, EventArgs e){
            startRot = (int)StartRotNumericUpDown.Value;
        }
        private void EndRotNumericUpDown_ValueChanged(object sender, EventArgs e){
            endRot = (int)EndRotNumericUpDown.Value;
        }
        private void LoopCheckBox_CheckedChanged(object sender, EventArgs e){
            if(LoopCheckBox.Checked){
                PartCountNumericUpDown.Visible = false;
                PartCountLabel.Visible = false;
            }
            else{
                PartCountNumericUpDown.Visible = true;
                PartCountLabel.Visible = true;
            }
        }
        private void InvertCheckBox_CheckedChanged(object sender, EventArgs e){
            if(InvertCheckBox.Checked){
                ShapeComboBox.SelectedIndex = 2;
                VelXNumericUpDown.ReadOnly = true;
                VelYNumericUpDown.ReadOnly = true;
                EndVelXNumericUpDown.ReadOnly = true;
                EndVelYNumericUpDown.ReadOnly = true;
            }
            else{
                VelXNumericUpDown.ReadOnly = false;
                VelYNumericUpDown.ReadOnly = false;
                EndVelXNumericUpDown.ReadOnly = false;
                EndVelYNumericUpDown.ReadOnly = false;
            }
        }
    }
}
